import hashlib
import socket
import json
import struct


class Client(object):
    login_status = False

    def __init__(self, ip, port):
        self.ip = ip
        self.port = port
        self.sock = socket.socket()
        self.sock.connect(('127.0.0.1', 8887), )

    def md5(self, pwd):
        """ 专门对密码进行加密，并返回加密后的密码 """
        return hashlib.md5(pwd.encode()).hexdigest()

    def send_msg(self, data):
        """ 将data字典序列化并且传递给对方 """
        head_data = json.dumps(data).encode()
        head_size = struct.pack('i', len(head_data))
        self.sock.send(head_size)
        self.sock.send(head_data)

    def recv_msg(self):
        """ 将对方传过来的报头大小和真实报头解析成字典并返回，它和send_msg搭配使用  """
        head_size = self.sock.recv(4)
        st_head_size = struct.unpack('i', head_size)[0]
        head_data = self.sock.recv(st_head_size)
        return json.loads(head_data.decode())

    def register(self):
        """ 专门负责注册逻辑的方法 """
        while True:
            user = input('user: ').strip()
            pwd = input('pwd: ').strip()
            if not user or not pwd:
                continue
            md_pwd = self.md5(pwd)
            data = {"user": user, "pwd": md_pwd, "action_type": "register"}
            self.send_msg(data)
            msg_data = self.recv_msg()
            if msg_data['code'] == 201:  # 用户已存在
                print(msg_data['code_content'])
            else:  # 注册成功
                print(msg_data['code_content'])
                break

    def login(self):
        """ 专门负责登录逻辑的方法 """
        if self.login_status:
            print('已为你自动登录....')
            return
        while True:
            user = input('user: ').strip()
            pwd = input('pwd: ').strip()
            if not user or not pwd:
                continue
            md_pwd = self.md5(pwd)
            data = {"user": user, "pwd": md_pwd, "action_type": "login"}
            self.send_msg(data)
            msg_data = self.recv_msg()
            if msg_data['code'] == 301:  # 用户名或者密码错误
                print(msg_data['code_content'])
                self.login_status = False
            else:  # 登录成功
                print(msg_data['code_content'])
                self.login_status = True
                break

    def q(self):
        """ 退出程序 """
        exit('你选择退出')

    def logout(self):
        """ 退出登录状态 """
        if self.login_status:
            self.login_status = False
            print(f'当前用户已退出.....')
        else:
            print('用户没有登录')

    def handler(self):
        """
        专门用于跟客户端转发消息的方法
        :return:
        """
        tmp_dict = {
            "1": ['登录', self.login],
            "2": ['注册', self.register],
            "3": ['退出', self.q],
            "4": ['退出登录状态', self.logout]
        }
        while True:
            for k, v in tmp_dict.items():
                print(k, v[0])
            choice = input('根据序号进行选择').strip()
            if not choice:  # 客户户端不能发送为空的消息
                continue
            if tmp_dict.get(choice):
                tmp_dict.get(choice)[-1]()
            else:
                print('不支持的功能')
            # self.sock.send(choice.encode())
            # msg = self.sock.recv(1024).decode()
            # print(msg)


if __name__ == '__main__':
    obj = Client('127.0.0.1', 8887)
    obj.handler()
